#pragma once
#include "../qbtools.h"
#include <QObject>
#include <qbmessage/include/message_bond.h>
#include <core/sync/lock.h>
#include <map>
#include <set>
#include <string>
#include <functional>

class PushMsgInfo;
typedef std::function<void(const PushMsgInfo&, const qb::SSAckMsg&)> NotifyFunc;

typedef void (*NotifyByParamFunc)(const qb::SSAckMsg&, NotifyFunc notify);
class S_TOOL_EXPORT PushMsgInfo
{
public:
	PushMsgInfo(int func, const std::string& p, NotifyByParamFunc f)
		: funcId(func), paramter(p), extractFuncPtr(f)
	{}
	bool operator<(const PushMsgInfo& other) const;
	bool operator==(const PushMsgInfo& other) const;
public:
	int funcId = 0;
	std::string paramter;
	NotifyByParamFunc extractFuncPtr = nullptr;
};

class MessageReceiver;
class RequestNotifier : public IQpidMessageProcessor
{
public:
	static RequestNotifier& instance();
	void registReqReceiver(int, MessageReceiver* pr);
	void unRegistReqReceiver(int, const MessageReceiver* pr);

	void registPushReceiver(const PushMsgInfo&, MessageReceiver* pr);
	void unRegistPushReceiver(const PushMsgInfo&, const MessageReceiver* pr);
protected:
	STDMETHOD_(void, OnResponse)(THIS_ int32_t funcId, const qb::SSAckMsg&);
	void notifyPushReceiver(const PushMsgInfo&, const qb::SSAckMsg&);

private:
	RequestNotifier() = default;
	std::map<int, MessageReceiver*> m_receivers;
	std::multimap<PushMsgInfo, MessageReceiver*> m_pushReceivers;
	std::multimap<PushMsgInfo, MessageReceiver*> m_pushReceiversCopy;
	std::map<int, NotifyByParamFunc>	m_paramExtractors;
	qb::base::Spinlock				m_lock;
	qb::base::Spinlock				m_delLock;
	qb::base::Spinlock				m_pushLock;
	qb::base::Spinlock				m_pushDelLock;
};

void S_TOOL_EXPORT registSpecificMsgProcessor();
void S_TOOL_EXPORT unRegistSpecificMsgProcessor();